/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package tni;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;

/**
 *
 * @author jgres
 */

public class Huffman {
ArrayList<Element> Liste;
ArrayList<Element> Arbre;

    Huffman(ArrayList<Element> Liste)
    {
        this.Liste = Liste;
    }

    Huffman(Hashtable<Character,Integer> hashtable, int size) // Cree la liste à partir d'une hashtable
    {
        this.Liste = new ArrayList<Element>();
        // Calcul de la probabilité pouyr chaque élement de hashtable
        Enumeration<Character> keys = hashtable.keys();
        Enumeration<Integer> values = hashtable.elements();

        while(keys.hasMoreElements()){
         double prob = (double) values.nextElement()/size;
         Liste.add(new Element(prob,String.valueOf(keys)));
         keys.nextElement();
        }     
     
    }

    Huffman(Hashtable<Integer, Integer> pixel, int size,int a) {

 this.Liste = new ArrayList<Element>();
        // Calcul de la probabilité pouyr chaque élement de hashtable
        Enumeration<Integer> keys = pixel.keys();
        Enumeration<Integer> values = pixel.elements();

        while(keys.hasMoreElements()){
         double prob = (double) values.nextElement()/size;
         Liste.add(new Element(prob,String.valueOf(keys)));
         keys.nextElement();
        }   

        
    }
  
    
        private ArrayList<Element> codage(ArrayList<Element> liste) {
        ArrayList<Element> liste2 = new ArrayList();

         if(liste.size()>1)
        {
        Element min = Element.getMin(liste,"min");
        Element max = Element.getMin(liste,"max");
        Element parent = new Element(min,max);
        min.initParent(parent);
        max.initParent(parent);
        min.initBit(1);
        max.initBit(0);
        // On creer un element qui sera l'element parent

        for(int i = 0; i < liste.size();i++)
        {
          if(liste.get(i).ID!=min.ID && liste.get(i).ID!=max.ID)
          {
              Element p = new Element(liste.get(i).val);
              liste.get(i).initParent(p);
              liste2.add(p);
          }
        }
        liste2.add(parent);
       return codage(liste2);

        }
        else
        {
            return liste;
        }
    }


        private void Calcul(ArrayList<Element> arbre, String s) {
        for(int i = 0; i < arbre.size();i++)
        {
            if(arbre.get(i).bit!=null)
                arbre.get(i).codage+=s+String.valueOf(arbre.get(i).bit);
            else
                arbre.get(i).codage+=s;


             if(arbre.get(i).enfant != null)
                Calcul(arbre.get(i).enfant,arbre.get(i).codage);
        }
    }


        public void ExecuteCodage()
        {
            this.Arbre=codage(this.Liste);
        }

        public void ExecuteCalcul()
        {
            Calcul(this.Arbre,"");
        }
        public void ExecuteAffich(boolean affichDetail)
        {
            double sum=0;
       double result=0;
       for(int i = 0; i< Liste.size();i++)
       {
           result = Liste.get(i).codage.length()*Liste.get(i).val;
          if(affichDetail)
              System.out.println(Liste.get(i).val+"*"+Liste.get(i).codage.length()+"="+result);

           sum+=result;

       }
        System.out.println("- Méthode de Huffman : L = "+sum);
        }

}
